<?php

namespace App\Models\Cruise;

use App\Enums\BaseErrorCode;
use App\Enums\Cruise\ErrCode;
use App\Exceptions\Custom\ResponseHttpException;
use App\Models\BaseModel;
use App\Models\Common\ResourcesModel;
use App\Models\Kms\User\KmsUser;
use App\Models\OpenShop\Common\OpenShopOrderManagerModel;
use App\Models\OpenShop\InvestmentPromotion\OpenShopAddressModel;
use App\Models\OpenShop\InvestmentPromotion\OpenShopMainProcessModel;
use App\Models\OpenShop\InvestmentPromotion\OpenShopUserBaseInfoModel;
use App\Models\OpenShop\InvestmentPromotion\OpenShopUserIdentityCardModel;
use App\Models\OpenShop\SiteLocation\OpenShopSiteLocationModel;
use App\Models\Shop\ShopModel;
use App\Models\Traits\KfSoftDeletes;
use App\Models\Traits\KfUid;
use App\Service\BaseService;
use App\Support\CustomForm\AttributeSupport;
use Illuminate\Database\Eloquent\Relations\HasMany;
use Illuminate\Database\Eloquent\Relations\HasManyThrough;
use Illuminate\Database\Eloquent\Relations\HasOne;
use Illuminate\Database\Eloquent\Relations\HasOneThrough;
use Illuminate\Support\Collection;

class CruiseOrderModel extends BaseModel
{
    protected $table = 'cruise_order';

    use KfUid;
    use KfSoftDeletes;

    protected $fillable = [
        'orderNo',
        'type',
        'status',
        'shopId',
        'templateId',
        'handlerId',
        'cruiseCheckCompanyId',
        'createdByUid',
        'extra',
    ];

    const TYPE_NEW_SHOP_HELP = 1;
    const TYPE_CHECK         = 3;
    const TYPE_COMPANY_CHECK = 5;
    const TYPE_CHECK_TOUR    = 6;
    const TYPE_ACTIVITY      = 9;

    const CRUISE_TYPE_MAPPING = [
        self::TYPE_NEW_SHOP_HELP => '新店帮扶',
        self::TYPE_CHECK         => '夸父稽核',
        self::TYPE_COMPANY_CHECK => '工厂稽核',
        self::TYPE_CHECK_TOUR    => '云巡店',
        self::TYPE_ACTIVITY      => '品牌运营项目',
    ];

    const STATUS_INIT       = 0; //初始化
    const STATUS_NOT_SUBMIT = 1; //待提交
    const STATUS_NOT_REVIEW = 2; //待审核
    const STATUS_NOT_MODIFY = 3; //待修改
    const STATUS_COMPLETE   = 4; //已完成
    const STATUS_CLOSED     = 5; //已作废
    const STATUS_EXPIRED     = 6; //已过期

    const STATUS_WAIT_MODIFY_EXT = 10; // 待三方审核
    const STATUS_COLLECTED       = 11; // 待领取
    const STATUS_AUDIT_OK        = 12; // 审核无异常
    const STATUS_AUDIT_ERROR     = 13; // 审核有异常

    const CRUISE_STATUS_MAPPING = [
        self::STATUS_INIT            => '进行中',
        self::STATUS_NOT_SUBMIT      => '待提交',
        self::STATUS_NOT_REVIEW      => '待审核', // 总部
        self::STATUS_NOT_MODIFY      => '待修改',
        self::STATUS_COMPLETE        => '已完成',
        self::STATUS_CLOSED          => '已作废',
        self::STATUS_EXPIRED         => '已过期',
        self::STATUS_WAIT_MODIFY_EXT => '待审核',
        self::STATUS_COLLECTED       => '待领取',
        self::STATUS_AUDIT_OK        => '审核无异常',
        self::STATUS_AUDIT_ERROR     => '审核有异常',
    ];

    /**
     * @return HasManyThrough
     */
    public function userIdentityCardRel(): HasManyThrough
    {
        return $this->hasManyThrough(
            OpenShopUserIdentityCardModel::class,
            OpenShopMainProcessModel::class,
            'shopId',
            'orderNo',
            'shopId',
            'orderNo');
    }


    /**
     * @return HasManyThrough
     */
    public function orderManagerRel(): HasManyThrough
    {
        return $this->hasManyThrough(
            OpenShopOrderManagerModel::class,
            OpenShopMainProcessModel::class,
            'shopId',
            'mainProcessId',
            'shopId',
            'id');
    }

    /**
     * @return HasOne
     */
    public function siteLocationRel(): HasOne
    {
        return $this->hasOne(OpenShopSiteLocationModel::class, 'orderNo', 'orderNo')->whereIn('source',
            [OpenShopSiteLocationModel::SOURCE_OPEN_SHOP, OpenShopSiteLocationModel::SOURCE_HOUSING]);
    }


    /**
     * @return HasOne
     */
    public function cruiseTemplateRel(): HasOne
    {
        return $this->hasOne(CruiseTemplateModel::class, 'id', 'templateId');
    }

    /**
     * @return HasOne
     */
    public function addressRel(): HasOne
    {
        return $this->hasOne(OpenShopAddressModel::class, 'orderNo', 'orderNo');
    }

    /**
     * @return HasOne
     */
    public function userBaseInfoRel(): HasOne
    {
        return $this->hasOne(OpenShopUserBaseInfoModel::class, 'orderNo', 'orderNo');
    }

    public function cruiseCheckSelfDetailRel(): HasOne
    {
        return $this->hasOne(CruiseCheckSelfDetailModel::class, 'cruiseOrderId');
    }

    public function cruiseOrderProcessV2Rel(): HasMany
    {
        return $this->hasMany(CruiseOrderProcessV2Model::class, 'cruiseOrderId', 'id');
    }

    public function cruiseOrderProcessV2LastRel(): HasOne
    {
        return $this->hasOne(CruiseOrderProcessV2Model::class, 'cruiseOrderId', 'id')
                    ->orderByDesc('id');
    }

    public function getExtraArrAttribute(): array
    {
        return json_decode($this->extra ?? '[]', true);
    }

    public static function getOrder(
        int $shopId,
        int $type = CruiseOrderModel::TYPE_NEW_SHOP_HELP,
        string $orderNo = '',
        bool $throw = true
    ): ?self {
        $orderModel = CruiseOrderModel::query()
                                      ->when($shopId, function ($query) use ($shopId) {
                                          $query->where('shopId', $shopId);
                                      })
                                      ->when($orderNo, function ($query) use ($orderNo) {
                                          $query->where('orderNo', $orderNo);
                                      })
                                      ->where('type', $type)
                                      ->first();

        if (!$orderModel) {

            if ($throw) {
                throw new ResponseHttpException(ErrCode::CODE_ERR_NO_HELP_CRUISE, null, "门店没有帮扶订单");
            } else {
                return null;
            }
        }

        $sysTemplate = (int)CruiseTemplateModel::query()->where('id', $orderModel->templateId)->value('sysTemplate');
        if (!CruiseOrderInputModel::getData($sysTemplate, $orderModel->id)) {

            if ($throw) {
                throw new ResponseHttpException(BaseErrorCode::$ERROR_OCCURRED, null, "门店没有帮扶订单表单，请联系管理员");
            } else {
                return null;
            }
        }

        return $orderModel;
    }

    /**
     * 初始化表记录
     * @param string $orderNo
     * @param int $shopId
     * @return \Illuminate\Database\Eloquent\Builder|\Illuminate\Database\Eloquent\Model
     */
    public function initShopHelper(string $orderNo, int $shopId, int $templateId)
    {
        $orderModel = self::query()->updateOrCreate(['orderNo' => $orderNo, 'type' => self::TYPE_NEW_SHOP_HELP], [
            'status'     => $status = self::STATUS_NOT_SUBMIT,
            'shopId'     => $shopId,
            'templateId' => $templateId,
        ]);

        $orderModel->getCurrentHandlerInfo($status);

        return $orderModel;
    }

    /**
     * 获取阶段对应处理人
     * @return array
     */
    public function getCurrentHandlerInfo(int $status): array
    {
        switch ($status) {
            case self::STATUS_NOT_SUBMIT:
            case self::STATUS_NOT_MODIFY:

                // 督导
                $mainProcessId = (int)OpenShopMainProcessModel::query()
                                                              ->where('orderNo', $this->orderNo)
                                                              ->orderBy('id', 'desc')
                                                              ->value('id');
                $manager       = OpenShopOrderManagerModel::query()
                                                          ->where('type', OpenShopOrderManagerModel::MANAGER_TYPE_5)
                                                          ->where('mainProcessId', $mainProcessId)
                                                          ->first();
                if (!$manager) {
                    throw new ResponseHttpException(BaseErrorCode::$ERROR_OCCURRED, null,
                        "找不到督导：{$this->orderNo}");
                }
                $arr = [
                    'id'   => (int)$manager['managerUid'],
                    'name' => (string)$manager['managerName'],
                ];

                break;
            case self::STATUS_NOT_REVIEW:
            case self::STATUS_COMPLETE:

                // 筹备审核
                $mainProcessId = OpenShopMainProcessModel::query()->where('shopId', $this->shopId)->value('id');
                $manager = OpenShopOrderManagerModel::query()
                                                     ->where('type', OpenShopOrderManagerModel::MANAGER_TYPE_4)
                                                     ->where('mainProcessId', $mainProcessId)
                                                     ->first();
                if (!$manager) {
                    BaseService::throwErr('找不到筹备顾问：' . $this->orderNo);
                }

                $arr = [
                    'id'   => (int)$manager->managerUid,
                    'name' => (string)$manager->managerName,
                ];

                break;
            default:
                return [];
        }

        // 校正handlerId
        if ($arr['id'] != $this->handlerId) {
            $this->handlerId = $arr['id'];
            $this->save();
        }

        return $arr;
    }

    //获得这个order下的所有任务
    public function cruiseCheckTaskRel(): HasOneThrough
    {
        return $this->hasOneThrough(
            CruiseCheckTaskModel::class,
            CruiseTaskOrderMappingModel::class,
            'orderId',
            'id',
            'id',
            'taskId'
        );
    }

    public function cruiseCheckSelfTaskRel(): HasOneThrough
    {
        return $this->hasOneThrough(
            CruiseCheckSelfTaskModel::class,
            CruiseCheckSelfDetailModel::class,
            'cruiseOrderId',
            'id',
            'id',
            'taskId'
        );
    }

    public function checkTaskDetailRel()
    {
        return $this->hasOne(CruiseCheckDetailModel::class, 'orderId', 'id');
    }

    /**
     * 关联流程进度
     * @return HasMany
     */
    public function cruiseOrderProcessRel(): HasMany
    {
        return $this->hasMany(CruiseOrderProcessModel::class, 'cruiseOrderId', 'id');
    }

    /**
     * 获取表单所有字段信息
     *
     * @param string $orderNo
     * @return array
     */
    public static function getOrderFormContent(string $orderNo): array
    {
        $cruiseOrderModel      = self::getOrder(0, CruiseOrderModel::TYPE_NEW_SHOP_HELP, $orderNo);
        $sysTemplate           = (int)CruiseTemplateModel::query()
                                                         ->where('id', $cruiseOrderModel->templateId)
                                                         ->value('sysTemplate');
        $cruiseOrderInputModel = CruiseOrderInputModel::getData($sysTemplate, $cruiseOrderModel->id);

        $cruiseOrderInput = $cruiseOrderInputModel->inputObjectJsonArr;
        $userContentArr   = $cruiseOrderInputModel->userContentJsonArr;

        // 资源素材
        $resource = (array)ResourcesModel::getModuleBusinessResources(ResourcesModel::MODULE_TYPE_CRUISE,
            ResourcesModel::BUSINESS_CRUISE_ORDERS, $cruiseOrderInputModel->orderId);

        foreach ($cruiseOrderInput as &$positions) {
            foreach ($positions['projects'] as &$project) {
                $projectObj = unserialize($project);
                $inputName  = $projectObj->getInputName();
                $inputType  = $projectObj->getInputType();
                if (isset($userContentArr[$inputName])) {
                    $projectObj->setValue($userContentArr[$inputName]);
                } elseif (isset($resource[$inputName])) {
                    $projectObj->setValue($resource[$inputName]);
                } else {

                    // 默认返回空字符串不给null
                    if (in_array($inputType,
                        [AttributeSupport::INPUT_TYPE_STRING, AttributeSupport::INPUT_TYPE_TEXT])) {
                        $projectObj->setValue("");
                    }
                }

                $project = $projectObj->build();
            }
        }

        $formAttributes = new Collection();
        collect($cruiseOrderInput)->each(function ($items) use (&$formAttributes) {
            $formAttributes = $formAttributes->merge($items["projects"]);
        });
        return [$formAttributes, $userContentArr];
    }

    /**
     * 工厂稽核关联
     * @return HasOne
     */

    public function cruiseCheckCompanyRel(): HasOne
    {
        return $this->hasOne(CruiseCheckCompanyModel::class, 'id', 'cruiseCheckCompanyId');
    }

    /**
     * 获取任务名称
     * @return string
     */
    public function getTaskName(int $cruiseCheckTaskId = 0): string
    {
        if ($this->cruiseCheckCompanyId) {

            $sysTemplate = (int)optional($this->checkTaskDetailRel)->sysTemplate;

            if ($sysTemplate == CruiseTemplateModel::SYS_TEMPLATE_FACTORY_SPECIAL) {

                // 专项-专项名称
                $checkTaskDetailRel = optional($this->checkTaskDetailRel)->cruiseTaskRel;
                $taskName           = optional($checkTaskDetailRel)->name;
            } elseif ($sysTemplate == CruiseTemplateModel::SYS_TEMPLATE_FACTORY_SELF) {

                // 自检-自检名称
                $selfTaskRel = optional($this->cruiseCheckSelfDetailRel)->cruiseCheckSelfTaskRel;
                $taskName    = optional($selfTaskRel)->name;
            } else {
                $taskName = '-';
            }
        } else {
            if ($cruiseCheckTaskId == 0) {
                $cruiseCheckTaskId = (int)optional($this->checkTaskDetailRel)->taskId;
            }
            $taskName = CruiseCheckTaskModel::query()->where('id', $cruiseCheckTaskId)->value('name');
        }

        return (string)$taskName;
    }


    // 开业报告关联资源表
    public function openReportFileRel(): HasOne
    {
        return $this->hasOne(ResourcesModel::class, 'businessId', 'id')->where('module', ResourcesModel::MODULE_TYPE_CRUISE)->where('business', ResourcesModel::BUSINESS_CRUISE_ORDERS)->where('name', 'like', "men_dian_men_tou_shi_jing%");
    }

    /**
     * @return HasOne
     */
    public function fsHandlerUserRel(): HasOne
    {
        return $this->hasOne(KmsUser::class, "rmsUserId", "handlerId");
    }

    public function shopRel(): HasOne
    {
        return  $this->hasOne(ShopModel::class,'id','shopId');
    }
}
